/*
 * Created by Jaren at 2021/12/13 13:53
 */
import 'dart:typed_data';

import 'package:inmotion_protocol/base/base_factory.dart';
import 'package:inmotion_protocol/base/base_message.dart';
import 'package:inmotion_protocol/base/file/file_manager.dart';
import 'package:inmotion_protocol/base/vehicle_data.dart';
import 'package:inmotion_protocol/common/accessory_info.dart';
import 'package:inmotion_protocol/common/assistant_settings.dart';
import 'package:inmotion_protocol/common/bms_log_manager.dart';
import 'package:inmotion_protocol/common/log_file_manager.dart';
import 'package:inmotion_protocol/common/media_file_upload_manager.dart';
import 'package:inmotion_protocol/common/fw_update_manager.dart';
import 'package:inmotion_protocol/common/product_model.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/common/response.dart';
import 'package:inmotion_protocol/common/riding_statistics_helper.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/lorin/bean/base/bms_info.dart';
import 'package:inmotion_protocol/lorin/bean/base/tbox.dart';
import 'package:inmotion_protocol/lorin/bean/base/tire_pressure_sensor.dart';
import 'package:inmotion_protocol/lorin/bean/common/date.dart';
import 'package:inmotion_protocol/lorin/bean/common/response/response.dart';
import 'package:inmotion_protocol/lorin/bean/common/bms_info.dart';
import 'package:inmotion_protocol/lorin/media/avatar_file_manager.dart';
import 'package:inmotion_protocol/protocol_worker.dart';

abstract class Protocol<T extends IMessage> {
  final ProtocolWorker<T> _protocolWorker;
  final MsgFactory<T> _msgFactory;
  ProtocolType type = ProtocolType.lorin;
  final ProductProperty productProperty = ProductProperty.instance;

  int maxSizePeerPkg = 220;

  Protocol(this._protocolWorker, this._msgFactory);

  void setup(ProductModel model, VersionWrapper version);

  void onDataReceived(Uint8ClampedList bytes, [String clientId = '']) {
    _protocolWorker.onDataReceived(bytes, clientId);
  }

  Future prepareOnLinkLayerConnected(String deviceName,
      {String clientId = '', bool resetData = true});

  void setUnhandledMsgHandler(Function f) {
    _protocolWorker.unhandledMsgHandler = f;
  }

  Future<TBoxInfo> requestTBoxRealTimeInfo();

  Future<List<EsimModel>> requestTBoxEsimList();

  Future<TBoxInfo> requestTBoxInfo();

  Future<bool> rebootTBox(int mode);

  Future<ProductProperty> requestProductProperty();

  Future<ProductProperty> requestProductPropertyV2();

  Future<RealTimeInfo> requestRealTimeInfo();

  Future<RealTimeState> requestRealTimeState();

  Future<RealTimeError> requestRealTimeError();

  Future<HistoryStatistics> requestCurrentStatistics();

  Future<StatisticsResponse> requestHistoryStatistics(int index, int count);

  Future<StatisticsInfoResponse> requestHistoryStatisticsInfo();

  Future<TotalStatistics> requestTotalStatistics();

  Future<BatteryRealTimeInfo> requestBatteryRealTimeInfo();

  Future<AllRealTimeData> requestAllRealTimeData();

  Future<VehicleSynthesizeRealTimeInfo> requestVehicleSynthesizeRealTimeInfo();

  Future<Settings> requestSettings();

  Future<void> respondQuickConnect();

  Future<DateTime> requestActivatedTime();

  Future<DeviceWrapper> requestDevicesId(List<int> devices);

  Future<AccessoryWrapper> requestAccessoriesInfo();

  Future<VersionWrapper> requestFwVersion([int? target]);

  Future<Uint8ClampedList> requestLightEffectMode();

  Future<bool> syncRTC(DateTime? dateTime);

  Future<SettingsResponse> lostMode([bool enable = true]);

  Future<bool> activate(DateTime dateTime);

  Future<SettingsResponse> lock([bool lock = true]);

  Future<SettingsResponse> setSpeedLimit(int speedLimit, [int? speedLimit2]);

  Future<SettingsResponse> headlightOnOff(
      {bool? on, bool? lowBeamOn, bool? highBeamOn});

  Future<SettingsResponse> daytimeRunningLightOnOff([bool on = true]);

  Future<SettingsResponse> spinKillOnOff([bool on = true]);

  Future<SettingsResponse> transportationModeOnOff([bool on = true]);

  Future<SettingsResponse> soundPackOnOff([bool on = true]);

  Future<SettingsResponse> autoHeadlightOnOff([bool on = true]);

  Future<SettingsResponse> soundWaveOnOff([bool on = true]);

  Future<SettingsResponse> loadDetectOnOff([bool on = true]);

  Future<SettingsResponse> noLoadDetectOnOff([bool on = true]);

  Future<SettingsResponse> fanOnOff([bool on = true]);

  Future<SettingsResponse> fanQuietModeOnOff([bool on = true]);

  Future<SettingsResponse> usbPowerOnOff([bool on = true]);

  Future<SettingsResponse> assistBalanceOnOff([bool on = true]);

  Future<SettingsResponse> lowBatLevelProtectionModeOnOff([bool on = true]);

  Future<SettingsResponse> tboxLowBatLevelWakeUpVehicleModeOnOff([bool on = true]);

  Future<SettingsResponse> showTboxInfoOnVehicleOnOff([bool on = true]);

  Future<SettingsResponse> remainderRangeEstimateOnOff([bool on = true]);

  Future<SettingsResponse> autoScreenOffOnOff([bool on = true]);

  Future<SettingsResponse> cruiseOnOff([bool on = true]);

  Future<SettingsResponse> safeSpeedLimitOnOff([bool on = true]);

  Future<SettingsResponse> bermAngleModeOnOff([bool on = true]);

  Future<SettingsResponse> zeroSpeedupOnOff(
      [bool on = true, AbsAssistanceSettings? assistanceSettings]);

  Future<SettingsResponse> hdcOnOff([bool on = true]);

  Future<SettingsResponse> hacOnOff([bool on = true]);

  Future<SettingsResponse> speedingBrakingOnOff([bool on = true]);

  Future<SettingsResponse> overSpeedWarningOnOff([bool on = true]);

  Future<SettingsResponse> setWarningLimitSpeed(int speed1, int speed2);

  Future<bool> bindTirePressureSensor(String sensorId);

  Future<SettingsResponse> tirePressureWarningOnOff([bool on = true]);

  Future<SettingsResponse> setLowTirePressureWarningThreshold(int threshold);

  Future<SettingsResponse> setLogoLightBrightness(int brightness);

  Future<SettingsResponse> setTurnSignalMode(int mode);

  Future<SettingsResponse> setBermAngle(int angle);

  Future<SettingsResponse> setOutputThreshold(int tiltBack, int warning1, int warning2);

  Future<List<TirePressureSensor>> searchTirePressureSensor();

  Future<SettingsResponse> resetTirePressureSensorSearchResult();

  Future<SettingsResponse> setVolume(int volume);

  Future<SettingsResponse> setSpeedLimitOfAssistMode(int speedLimit);

  Future<SettingsResponse> setAutoHeadlightBrightnessThr(
      int lowThr, int highThr);

  Future<SettingsResponse> autoLowHighBeamOnOff([bool on = true]);

  Future<SettingsResponse> onePedalModeOnOff([bool on = true]);

  Future<SettingsResponse> brakeFirstModeOnOff([bool on = true]);

  Future<SettingsResponse> setAutoLowHighBeamSwitchSpeedThr(int speedThr);

  Future<SettingsResponse> setSoundWaveSensitivity(int sensitivity);

  Future<SettingsResponse> setPedalSensitivity(int sensitivity,
      [int? sensitivity2]);

  Future<SettingsResponse> setHeadlightBrightness(
      {int? brightness, int? lowBeamBrightness, int? highBeamBrightness});

  Future<SettingsResponse> setStandbyTime(int seconds);

  Future<SettingsResponse> setParkTime(int seconds);

  Future<SettingsResponse> setSpeedingBrakingSensitivity(
      int speeding, int braking);

  Future<SettingsResponse> setPitchAngleZero(int angle);

  Future<SettingsResponse> setRidingMode(int mode, [var param]);

  Future<SettingsResponse> setAssistantMode(int mode, [var param]);

  Future<SettingsResponse> setDriveMode(int mode);

  Future<SettingsResponse> setAccForce(int force, {int? type});

  Future<SettingsResponse> setBrakeForce(int force, {int? type});

  Future<SettingsResponse> setSoundPackId(int id);

  Future<SettingsResponse> setLightEffectId(int id, [int? color]);

  Future<SettingsResponse> setPassword(String pwd, [int? type]);

  Future<SettingsResponse> setPasswordType(int type);

  Future<SettingsResponse> setDeviceName(String name);

  Future<SettingsResponse> requestDeviceName();

  Future<SettingsResponse> setLightEffectMode(
      {bool? onOff, int? mode, int? paramColor, int? paramMode});

  Future<SettingsResponse> setSpeedUnit(int unit);

  Future<SettingsResponse> disableChargeDangerAlert();

  Future<SettingsResponse> gpsOnOff([bool on = true]);

  Future<SettingsResponse> powerOnOff([bool on = true]);

  Future<SettingsResponse> twoBatteryMode([bool on = true]);

  Future<SettingsResponse> setLanguage(int language);

  Future<SettingsResponse> setTurningSensitivity(int sensitivity);

  Future<SettingsResponse> startCalibration(int which);

  Future<AbsCalibrationResultResponse> queryCalibrationResult(int which);

  Future<SettingsResponse> startAccHandleCalibration();

  Future<SettingsResponse> startBrakeHandleCalibration();

  Future<SettingsResponse> startBalanceCalibration();

  Future<SettingsResponse> startTurningCalibration();

  Future<AbsCalibrationResultResponse> queryIMUCalibrationResult();

  Future<AbsCalibrationResultResponse> queryHandleCalibrationResult(
      [int which]);

  Future<SettingsResponse> playSoundItem(int index);

  Future<SettingsResponse> horn();

  Future<bool> buildSecurityConnection();

  Future<void> requestRebootHmic();

  Future<SettingsResponse> factoryReset({int level = 1});

  Future<FileResponse> openFile(
      {int? target, int? openType, String? name, int? type, int? tag});

  Future<FileResponse> writeFile(Uint8ClampedList content,
      {int? tab,
      int? target,
      int? fileHandle,
      int? offset,
      int? contentLength});

  Future<FileResponse> getFile(
      {int? tab,
      int? target,
      int? fileHandle,
      int? offset,
      int? contentLength});

  Future<FileResponse> checkFile(
      {int? target,
      int? fileHandle,
      int? offset,
      int? length,
      Uint8ClampedList? check});

  Future<FileResponse> getFileCheck(
      {int? target, int? fileHandle, int? offset});

  Future<FileResponse> closeFile({int? target, int? fileHandle});

  Future<FileResponse> setFileOffset({int? type, int? offset});

  Future<FileResponse> deleteFile(String path, {int? target});

  Future<SettingsResponse> startUpdate(int target, {Uint8ClampedList? para});

  Future<SettingsResponse> startTransfer(int target, {Uint8ClampedList? para});

  Future<FileListResponse> getFileList({Object? filter});

  Future<SettingsResponse> writeForceUpdate(
      int level, String minVersion, String maxVersion);

  Future<FirmwareState> requestFirmwareState();

  FwUpdateManager createFwUpdateManager(LinkLayerDeviceHandler handler,
      RequiredManualOperationHandler requiredManualOperationHandler);

  IFileManager createFileUploadManager(FileConfig config);

  IFileManager createFileDownloadManager(FileConfig config);

  SoundFileUploadManager createSoundFileUploadManager();

  LightEffectPkgFileUploadManager createLightEffectPkgUploadManager();

  AvatarFileManager createAvatarFileManager();

  LogFileManager createLogFileManager();

  RidingStatisticsHelper createRidingStatisticsHelper();

  Future<int> getRemainStorageCapacity({int diskIndex = 0});

  Future<FileResponse> renameFile(String filePath, String newFilePath);

  Future<List<int>> getSoundPackIdList({int? currentSoundPackId});

  Future<FileResponse> deleteSoundPack(int id);

  Future<FileResponse> deleteDiySoundItem(int soundIndex);

  Future<List<int>> getSoundItemIndexList();

  Future<List<int>> getLightEffectPkgIdList();

  Future<FileResponse> deleteLightEffectPkg(int id);

  Future<SettingsResponse> setMaxChargeLevel(int level);

  Future<SettingsResponse> setMaxDcOutputLevel(int level);

  Future<SettingsResponse> setUSBMode(int mode);

  Future<BMSFixedInfo> requestBMSFixedInfo(int which);

  Future<Datetime> requestBMSDate(int which);

  Future<BMSAllRealTimeInfo> requestBMSRealTimeInfo(int which);

  Future<AbsBMSCellsVoltage> requestBMSCellsVoltage(int target);

  AbsBmsLogManager createBMSLogManager();

  Future<SettingsResponse> startMotorAutoCalibration(
      {int hallOffsetCorrect = 1, int hallSectorCorrect = 1});

  Future<AbsCalibrationResultResponse> queryMotorAutoCalibrationResult();

  Future<SettingsResponse> resetMotorAutoCalibrationEffect(
      {int hallOffset = 1, int hallSector = 1});

  Future<SettingsResponse> stopMotorAutoCalibration();

  Future<SettingsResponse> startMotorSelfCheck({int method = 1});

  Future<AbsCalibrationResultResponse> queryMotorSelfCheckResult();

  Future<SettingsResponse> stopMotorSelfCheck();

  Future<SettingsResponse> startBatteryCalibration();

  Future<SettingsResponse> setMaxChargeCurrent(int currentAc220, int currentAc110);

  Future<SettingsResponse> setChargeLimitPercentage(int percentage);

  Future<SettingsResponse> backwardOverspeedAlterOnOff([bool on = true]) {
    throw UnimplementedError();
  }

  Future<SettingsResponse> sideWheelLightEffectOnOff([bool on = true]) {
    throw UnimplementedError();
  }

  Future<T> sendTransparentData(T msg) {
    throw UnsupportedError("");
  }

  Future<AbsCalibrationResultResponse> queryBatteryCalibrationResult();

  ProtocolWorker<T> protocolWorker() {
    return _protocolWorker;
  }

  MsgFactory<T> msgFactory() {
    return _msgFactory;
  }
}

/// [MethodComposer]向上屏蔽了不同产品类型部分接口的实现差异
/// 每个产品型号应实现该型号自己的[MethodComposer]
abstract class MethodComposer<T extends IMessage, M extends MsgFactory<T>> {
  ProtocolWorker<T> protocolWorker;
  MsgFactory msgFactory;
  ProductProperty property;

  MethodComposer(this.protocolWorker, this.msgFactory, this.property);

  Future<AllRealTimeData> requestAllRealTimeInfo();

  Future<Settings> requestSettings();
}

enum ProtocolType { lorin, ezCAN, elephant }
